package com.example.shirodemo.config.custom;

import com.example.shirodemo.service.PermissionService;
import java.util.List;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author 绫小路
 * @date 2021/1/10 19:54
 * @description
 */
public class PermissionFilter extends AccessControlFilter {

  private static final String UN_RESPONSE_MESSAGE = "{\"timestamp\":%d,\"code\":1,\"message\":\"未授权资源，无权限执行操作\"}";

  @Autowired
  private PermissionService permissionService;

  @Override
  protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
    // 1、判断登录
    Subject subject = SecurityUtils.getSubject();
    if (!subject.isAuthenticated()) {
      // 通过阅读源码，AccessControlFilter的protected void saveRequestAndRedirectToLogin(ServletRequest request, ServletResponse response)
      // 跳转到登录才是正确姿势
      saveRequestAndRedirectToLogin(request, response);
    }

    //2、判断url权限
    HttpServletRequest httpRequest = WebUtils.toHttp(request);
    String uri = httpRequest.getRequestURI();
    //获取访问此URL的角色
    List<String> roles = permissionService.getPermissionRole(uri, httpRequest.getMethod());
    if (!roles.isEmpty()) {
      for (String role : roles) {
        if (subject.hasRole(role)) {
          return true;//存在访问角色，放行
        }
      }
    }

    //401 返回json数据，此处可灵活使用 HttpServletRequest HttpServletResponse 转发到你想要的页面
    HttpServletResponse httpResponse = WebUtils.toHttp(response);
    httpResponse.setStatus(HttpServletResponse.SC_OK);//将401设置为OK
    httpResponse.setHeader("Content-type", "application/json;charset=utf-8");
    httpResponse.setCharacterEncoding("UTF-8");//防止中文乱码
    httpResponse.getWriter().write(String.format(UN_RESPONSE_MESSAGE, System.currentTimeMillis()));
    return false;
  }

  @Override
  protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
    return false;
  }
}
